Datenbank-Container

Rainer Becker

Die wesentliche Erweiterung von Visual FoxPro im Datenbankbereich sind die neuen Datenbank-Container. Ein DBC fast bestehende Tabellen zu einer Gesamt-Datenbank zusammen und ist selbst auch wieder nur eine Tabelle. Die Gesamtheit von Datenbank-Container mit allen in ihm definierten Tabellen ergibt dann die eigentliche Datenbank.

Diese ist physisch zwar über verschiedene Plätze verstreut, logisch aber eine Einheit. Den DBC sollte man jedoch keinesfalls mit einem Data-Dictionary verwechseln, denn die Tabellenstrukturen befinden nach wie vor im Header der DBF-Datei und die Indexstrukturen sind nach wie vor im Header der CDX-Datei. Der Datenbank-Container ist also nur zusätzlich/ergänzend zu vorhandenen Tabellen. Ein Neuerzeugen von Tabellen oder Indizes ist aus den Informationen im Datenbank-Container nicht möglich.

Grundbefehle

Für das Arbeiten mit dem Datenbankcontainer gibt es ein halbes Dutzend neuer Grundbefehle. Erstmal legt man sich einen leeren DBC mit CREATE DATABASE an. Öffnen und Schließen kann man ihn mit OPEN bzw. CLOSE DATABASE. Visuell ändern kann man einen Container dann mit MODIFY DATABASE. Und da man jede Menge Container offen haben kann, muß man zwischen ihnen ja auch wechseln können. Dafür ist SET DATABASE TO zuständig. Falls man einen DBC wieder loswerden will darf man ihn nur mit dem Befehl DELETE DATABASE löschen, da sonst die Referenzen in den verbundenen Tabellen nicht entfernt werden und man diese nicht mehr ohne weiteres öffnen kann. Wahlweise kann man mit der zusätzlichen Befehlsklausel DELETETABLES die Tabellen auch gleich mitlöschen. Wenn einem das versehentlich passiert, hat man einen schnellen Super-ZAP, zu der langsamen Variante kommen wir später.

Inhaltsanzeige

Für die Anzeige des Inhalts eines Datenbankcontainers gibt es eine Reihe neuer Klauseln für entsprechende LIST bzw. DISPLAY-Befehle. Interaktiv Anzeigen lassen kann man sich den Gesamtinhalt (LIST / DISPLAY DATABASE), die enthaltenen Tabellen (LIST / DISPLAY TABLES), die enthaltenen Views (LIST / DISPLAY VIEWS), die definierten ODBC-Verbindungen (LIST / DISPLAY CONNECTIONS) sowie die gespeicherten Prozeduren/Funktionen (LIST / DISPLAY PROCEDURES). Per Umleitung der Ausgabe in eine Textdatei kann man so auch schnell Vorlagen für eine Dokumentation erstellen.

Sonstige Befehle

Zwar sind Datenbankcontainer eigentlich auch nur Tabellen, aber die Funktionen DBF() und USED() kann man auf diese leider nicht anwenden. Stattdessen gibt es DBC() und DBUSED().

Zur schnellen Information über Datenbankcontainer gibt es die Funktion ADATABASES(), die ein Array aller offenen Datenbankcontainer zurückliefert, sowie ADBOBJECTS() mit einem Array aller Einträge im aktuellen Datenbankcontainer.

Um Details über die Eigenschaften eines DBCs zu ermitteln oder zu setzen, gibt es das neue Funktionspaar DBGETPROP() und DBSETPROP(). Get- und Set-Funktionen für Properties begegnen einem in Visual FoxPro übrigens häufiger und sie sind alle sehr ähnlich. Bei häufigen Änderungen der im DBC enthaltenen Einträge sowie nach dem Entfernen von Tabellen kann man den DBC mit PACK DATABASE wie eine normale Tabelle komprimieren. Zusätzlich gibt es noch eine Verifizier-Funktion zwecks Abgleich der im Container gespeicherten Strukturen mit den real vorhandenen Tabellen. VALIDATE DATABASE liefert derzeit leider nur eine interaktive Fehlermeldung zurück und keine Fehlernummer.

Tabellen und Container

Nicht nur mit dem kleinen DBC-Toolbar kann man bestehende Tabellen in einen DBC einfügen, sondern auch programmatisch ist dies mit ADD TABLE möglich. Ob eine Tabelle in einen Container eingefügt wurde, kann man mit der Funktion INDBC() abfragen. Mit REMOVE TABLE kann man aus dem aktiven Datenbankcontainer eine Tabelle entfernen. Der Rückverweis in der Tabelle wird gleichzeitig mit entfernt. Mit der zusätzlichen Befehlsklausel DELETE kann man auch gleich die Tabelle selbst löschen lassen Alternativ gibt es noch den Befehl FREE TABLE, welcher nur die Rückreferenz in der Tabelle auf den Container entfernt.

Felder in Tabellen

Jetzt haben wir die Tabellen im Container, der nächste Schritt ist jetzt die Feindefinition der Felder innerhalb der Tabellen. Und da ergeben sich mit dem DBC doch sehr praktikable neue Fähigkeiten. Außer das Tabellennamen und Feldbezeichnungen im Container bis zu 128 Zeichen lang sein können, gibt es je Feld auch noch ein halbes Dutzend neuer Eigenschaften.

Die erste Feldeigenschaft stellt sich als weitere Spalte im MODI-STRU-Dialog dar und hat die Überschrift NULL. Damit kann man bei SET NULL ON festlegen, daß ein Feld auch den Wert .NULL. enthalten darf. Bitte nur verwenden, wenn einem wirklich klar ist, worauf man sich da eigentlich einläßt. Unter DEFAULT kann man endlich Default-/Vorgabe-Wert für neue Sätze festlegen. Bei APPEND BLANK oder INSERT stehen die Vorgaben automatisch in den ansonsten leeren Feldern. Dabei muß es sich übrigens nicht um Konstanten handeln, sondern auch Funktionsaufrufe sind zulässig. Letzteres sei insbesondere bei Feldern die zu einem CANDIDATE- oder PRIMARY-Schlüssel gehören sehr empfohlen, weil man sonst sofort eine Fehlermeldung bekommt.

Mit dem Zusatzfeld CAPTION kann man endlich Überschriften eingeben und muß sich Kopfzeilen für BROWSE-Fenster nicht mehr mühsam selbst zusammenstellen. Außerdem verwendet der Masken-Assistent die CAPTION für den Feldtitel in neu erstellten Masken. Für Grids wird die Caption zwar nicht automatisch mit eingebaut, aber man kann sich diese ja zur Laufzeit mit DBGETPROP() aus dem Datenbankcontainer laden.

Richtig spannend wird es bei der Eigenschaft VALIDATION RULE. Hier benennt man eine Valid-Klausel auf Feldebene, die man sinnvoller Weise gleich im DBC direkt abspeichert (siehe unten). Je nach Einstellung beim Buffering wird diese beim Verlassen vom Datenfeld oder erst beim eigentlichen Abspeichern ausgewertet. Die entsprechende Textmeldung im Fehlerfall kann man gleich in VALIDATION TEXT ablegen. Eine VALIDATION RULE und einen VALIDATION TEXT kann man übrigens in einer Zusatzmaske nicht nur zu einem Datenfeld sondern auch gleich zum ganzen Datensatz abspeichern.

An die Dokumentation wurde ansonsten auch etwas mehr gedacht als früher und man kann in COMMENT einen Kommentar oder eine Notiz zum Feld eingeben.

Primärschlüssel

Auch im Bereich der Indizes gibt es noch eine weitere Neuerung. Diese ist aber eher kosmetischer Natur. Bisher kannten wir ja schon die Indexarten REGULAR und UNIQUE. Neu ist die Indexart CANDIDATE, die wirklich eindeutig ist und bei Einfügeversuchen von Duplikaten mit einer Fehlermeldung reagiert. Im Datenbank-Container kann man nunmehr einen beliebigen CANDIDATE-Index (es könnte evtl. ja mehrere geben und alle sind "Kandidaten" oder deutsch "Alternativschlüssel") zum Primärschlüssel, kurz PRIMARY, erklären. Welcher Index der Primärschlüssel ist, kann mit der Funktion PRIMARY() abgefragt werden. Soviel dazu. Was es leider nicht gibt, ist ein Zählerfeld bzw. ein inkrementeller Index (soetwas wie eine wirklich eindeutige Satznummer, die auch ein PACK überlebt). Aber dies kann man sich relativ einfach selbst bauen.

Gespeicherte Prozeduren

Gespeicherte Prozeduren, besser bekannt unter der englischen Bezeichnung "Stored Procedures", werden ebenfalls im Datenbankcontainer verwaltet. Die Implementation entspricht vielleicht nicht ganz der einschlägigen Fachliteratur, ist aber sehr sehr gut gelungen. Im Prinzip kann man beliebige Funktionen und Prozeduren direkt im Datenbankcontainer speichern und in der Praxis wirkt sich das wie eine Datenbank-spezifische Prozedur-Datei a la SET PROCEDURE TO aus. Mit LIST PROCEDURE kann man sich eine Übersicht über die Funktionsnamen geben und mit MODIFY PROCEDURE kann man ein Bearbeitungsfenster dafür öffnen. Der Befehl COPY PROCEDURES dient zum Exportieren der Prozeduren eines Containers in eine Textdatei. Und mit APPEND PROCEDURES kann man Prozeduren aus einer Datei anhängen oder optional mit der Klausel OVERWRITE die bestehenden Funktionen überschreiben. Die beiden letztgenannten Befehle waren zumindest in der Beta-Phase sehr wichtig, da sich die DBC-Strukturen öfters änderten und man so wenigstens seine Programme retten konnte. Und was für Funktionen speichert man nun an dieser Stelle statt irgendwo im Programm? Alle Funktionen die von Feldern oder Tabellen im Container beim Speichern von Datensätzen aufgerufen werden könnten! Dadurch bilden Daten und zugehörige Funktionen eine Einheit und diese sollte man soweit wie möglich kapseln - damit auch der zukünftige ODBC-Treiber diese verwenden kann und auch "Kurpfuscher" mit Excel einem keinen Schrott mehr in die Tabellen hauen können!

Zusammenfassung

Die wesentliche Eigenschaften des Datenbankcontainers in Bezug auf Tabellen haben wir nun behandelt. Wichtig und interessant sind aber auch die neuen Möglichkeiten zur Definition von Relationen sowie die darauf beruhenden Trigger zur Einhaltung der referentiellen Integrität. Und sehr praktisch sind die neuen lokalen und remote SQL-Views - dazu in einem anderen Artikel mehr.

Rainer Becker, seit 1985 in der Programmierung tätig, ist Geschäftsführer der ISYS GmbH sowie der W&B GmbH und leitet die deutschsprachige FoxPro User Group. Tätigkeitsschwerpunkte sind Beratung/Coaching für FoxPro-Projekte sowie die Entwicklung von Lösungen im Verlags- und Schulbereich. Sie erreichen Ihn unter redaktion@dfpug.de oder per Telefax unter 06173-950904.

CopyRight © 1996 by dFPUG c/o ISYS GmbH bzw. beim entsprechenden Verfasser